package com.openatc.agent.service.arterial;

import algorithm.Greenwave;
import algorithm.Kdalgorithm;
import com.openatc.model.model.Split;
import com.openatc.optimize.fixedtimeplan.config.cross.PhaseOpt;
import com.openatc.optimize.fixedtimeplan.enums.OptTypeEnum;
import model.RouteIntsection;
import model.RouteOpt;
import model.RoutePara;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * @author ：panleilei
 * @description
 * @modified By：
 * @version:
 * @date ：Created in 2024/1/23 16:31
 */
@Component
public class MotorcadeEndStrategy extends AbstractArterialTrafficControl {
    private Kdalgorithm kdalgorithm = new Kdalgorithm();
    @Override
    public String strategy() {
        return ArterialTrafficControlStrategies.MOTORCADEEND.getStrategy();
    }

    @Override
    public RouteOpt optimize(RoutePara routePara) {
        List<RouteIntsection> devs = routePara.getDevs();

        RouteOpt routeOpt = new RouteOpt();
        routeOpt.setDevs(devs);

        int offsets[] = new int[routePara.getDevs().size()]; // 保存优化后的相位差
        int intssplit[] = new int[routePara.getDevs().size()]; // 保存路口协调相位绿信比的值
        int intsdistances[] = new int[routePara.getDevs().size()]; // 保存各路口的距离
        int keyCycle = calKeyIntersectionCycle(routePara.getKeyintsid(), devs);
        // 初始化各路口协调相位绿信比
        for (RouteIntsection dev : devs) {
            String fixedtimeplantype = dev.getFixedtimeplantype();
            if (!StringUtils.hasLength(fixedtimeplantype)) {
                optType = OptTypeEnum.CYCLE_OPT;
            } else {
                optType = OptTypeEnum.getOptTypeEnumByValue(fixedtimeplantype);
            }
            List<PhaseOpt> phases = dev.getPhases();
            // 优化各路口周期
            cycleopt(keyCycle,dev.getFeature(), phases);
            // 保存周期
            offsets[dev.getSortid() - 1] = dev.getFeature().getPatternList().get(0).getOffset();
            // 保存各路口距离
            intsdistances[dev.getSortid() - 1] = dev.getDistance();
            // 协调相位号
            int phaseno;
            if (routePara.getDirection().equals("up")) {
                phaseno = dev.getForwardphaseid();
            } else {
                phaseno = dev.getBackphaseid();
            }

            List<List<Split>> rings = dev.getFeature().getPatternList().get(0).getRings();
            // 获取参与协调相位的绿信比
            label:
            for (int i = 0; i < rings.size(); i++) {
                for (Split split : rings.get(i)) {
                    if (phaseno == split.getId()) {
                        intssplit[dev.getSortid() - 1] = split.getValue();
                        break label;
                    }
                }
            }
        }

        List<RouteIntsection> routeOptList = routeOpt.getDevs();

        // 协调速度
        double speed = getCoordinationSpeed(routePara);
        // 计算每个路口的相位差
        // 上行
        if (routePara.getDirection().equals("up")) {
            for (RouteIntsection dev : routeOptList) {
                int distance = dev.getDistance();
                offsets = kdalgorithm.motorcadeOffsetOptUp(distance, speed, intssplit, keyCycle, dev.getSortid(), offsets);
            }
        }
        // 下行
        else {
            Collections.reverse(routeOptList);
            for (RouteIntsection dev : routeOptList) {
                offsets = kdalgorithm.motorcadeOffsetOptDown(speed, intssplit, keyCycle, dev.getSortid(), offsets, intsdistances);
            }
            Collections.reverse(routeOptList);
        }

        for (RouteIntsection dev : routeOptList) {
            // 改变路口相位差
            dev.getFeature().getPatternList().get(0).setOffset(offsets[dev.getSortid() - 1]);
        }
        // 获取Wave
        String type = routePara.getDirection(); // 上行/下行
        Greenwave greenwave;
        int width = kdalgorithm.getMotorcadeWidth(intssplit);
        if (routePara.getDirection().equals("up")) {
            greenwave = kdalgorithm.getMUp(type, speed, width);
        } else {
            greenwave = kdalgorithm.getMDown(type, speed, width);
        }
        List<Greenwave> greenwaves = new LinkedList<>();
        greenwaves.add(greenwave);

        routeOpt.setGreenwave(greenwaves);
        return routeOpt;
    }
}
